package yxy.banana.socket.receiver;

import java.util.concurrent.ConcurrentHashMap;

import yxy.apple.protobuf.Message.Parcal;
import yxy.apple.util.scheduler.Schedulable;
import yxy.apple.util.scheduler.ScheduledFuture;
import yxy.apple.util.scheduler.SingleThreadScheduler;

public class Observer {

	public static final Observer shared = new Observer();

	protected final SingleThreadScheduler<Schedulable> scheduler = new SingleThreadScheduler<>();

	protected final ConcurrentHashMap<String, Task> mapping = new ConcurrentHashMap<>();

	private static class Task {
		private ScheduledFuture future = null;
		private Receivable receiver = null;
	}

	public void observe(String tag, long timeout, Receivable receiver) {
		final Task task = new Task();
		task.receiver = receiver;
		task.future = this.scheduler.schedule(new Schedulable() {
			@Override
			public void trigger() {
				task.receiver.exipred(tag);
			}

			@Override
			public void cancelled() {
			}
		}, (int) timeout);
		this.mapping.put(tag, task);
	}

	public void neglect(String tag) {
		Task task = this.mapping.remove(tag);
		if (task != null) {
			task.future.cancel();
		}
	}

	public boolean detect(Parcal parcal) {
		boolean result = false;
		String tag = parcal.getTag();
		if (tag != null) {
			Task task = this.mapping.remove(tag);
			if (task != null) {
				task.future.cancel();
				task.receiver.receive(parcal);
				result = true;
			}
		}
		return result;
	}

	public void clear() {
		this.scheduler.clear();
		this.mapping.clear();
	}

}
